package com.docmgmt.mvp.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.docmgmt.mvp.dto.*;
import com.docmgmt.mvp.entity.RoleEntity;
import com.docmgmt.mvp.entity.UserEntity;
import com.docmgmt.mvp.entity.UserRoleEntity;
import com.docmgmt.mvp.exception.BusinessException;
import com.docmgmt.mvp.mapper.RoleMapper;
import com.docmgmt.mvp.mapper.UserMapper;
import com.docmgmt.mvp.mapper.UserRoleMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户服务（v3.0 CRUD完整实现）
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserService {

    private final UserMapper userMapper;
    private final RoleMapper roleMapper;
    private final UserRoleMapper userRoleMapper;
    private final PasswordEncoder passwordEncoder;

    /**
     * 创建用户
     *
     * @param request 创建请求
     * @return 用户VO
     */
    @Transactional
    public UserVO createUser(CreateUserRequest request) {
        log.info("创建用户: username={}, email={}", request.getUsername(), request.getEmail());

        // 1. 校验用户名唯一性
        UserEntity existingUser = userMapper.selectByUsername(request.getUsername());
        if (existingUser != null) {
            throw new BusinessException("用户名已存在");
        }

        // 2. 校验邮箱唯一性
        UserEntity existingEmail = userMapper.selectByEmail(request.getEmail());
        if (existingEmail != null) {
            throw new BusinessException("邮箱已被使用");
        }

        // 3. 创建用户实体
        UserEntity user = new UserEntity();
        user.setUsername(request.getUsername());
        user.setPasswordHash(passwordEncoder.encode(request.getPassword()));
        user.setEmail(request.getEmail());
        user.setFullName(request.getFullName());
        user.setPhone(request.getPhone());
        user.setAvatarUrl(request.getAvatarUrl());
        user.setDepartmentId(request.getDepartmentId());
        user.setStatus(request.getStatus() != null ? request.getStatus() : "active");
        user.setStorageQuota(request.getStorageQuota() != null ? request.getStorageQuota() : 5L * 1024 * 1024 * 1024);
        user.setStorageUsed(0L);

        userMapper.insert(user);
        log.info("用户创建成功: userId={}", user.getId());

        // 4. 分配角色（如果提供）
        if (request.getRoles() != null && !request.getRoles().isEmpty()) {
            assignRolesToUser(user.getId(), request.getRoles());
        } else {
            // 默认分配 member 角色
            RoleEntity memberRole = roleMapper.selectByRoleCode("member");
            if (memberRole != null) {
                UserRoleEntity userRole = new UserRoleEntity();
                userRole.setUserId(user.getId());
                userRole.setRoleId(memberRole.getId());
                userRoleMapper.insert(userRole);
            }
        }

        // 5. 返回用户VO
        return toUserVO(user);
    }

    /**
     * 更新用户
     *
     * @param userId  用户ID
     * @param request 更新请求
     * @return 用户VO
     */
    @Transactional
    public UserVO updateUser(Long userId, UpdateUserRequest request) {
        log.info("更新用户: userId={}", userId);

        // 1. 查询用户
        UserEntity user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 2. 校验邮箱唯一性（如果修改了邮箱）
        if (request.getEmail() != null && !request.getEmail().equals(user.getEmail())) {
            UserEntity existingEmail = userMapper.selectByEmail(request.getEmail());
            if (existingEmail != null) {
                throw new BusinessException("邮箱已被使用");
            }
            user.setEmail(request.getEmail());
        }

        // 3. 更新用户信息
        if (request.getFullName() != null) {
            user.setFullName(request.getFullName());
        }
        if (request.getPhone() != null) {
            user.setPhone(request.getPhone());
        }
        if (request.getAvatarUrl() != null) {
            user.setAvatarUrl(request.getAvatarUrl());
        }
        if (request.getDepartmentId() != null) {
            user.setDepartmentId(request.getDepartmentId());
        }
        if (request.getStatus() != null) {
            user.setStatus(request.getStatus());
        }
        if (request.getStorageQuota() != null) {
            user.setStorageQuota(request.getStorageQuota());
        }

        userMapper.updateById(user);
        log.info("用户更新成功: userId={}", userId);

        // 4. 更新角色（如果提供）
        if (request.getRoles() != null) {
            assignRolesToUser(userId, request.getRoles());
        }

        // 5. 返回用户VO
        return toUserVO(user);
    }

    /**
     * 删除用户（软删除）
     *
     * @param userId 用户ID
     */
    @Transactional
    public void deleteUser(Long userId) {
        log.info("删除用户: userId={}", userId);

        UserEntity user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // MyBatis-Plus 自动处理软删除（@TableLogic）
        userMapper.deleteById(userId);

        // 同时删除用户角色关联
        userRoleMapper.delete(new LambdaQueryWrapper<UserRoleEntity>()
                .eq(UserRoleEntity::getUserId, userId));

        log.info("用户删除成功: userId={}", userId);
    }

    /**
     * 获取用户详情
     *
     * @param userId 用户ID
     * @return 用户VO
     */
    public UserVO getUserDetail(Long userId) {
        log.info("获取用户详情: userId={}", userId);

        UserEntity user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        return toUserVO(user);
    }

    /**
     * 获取用户列表（分页）
     *
     * @param page      页码
     * @param pageSize  每页大小
     * @param keyword   搜索关键词（用户名/全名/邮箱）
     * @param status    状态过滤
     * @param departmentId 部门ID过滤
     * @return 分页结果
     */
    public PagedResult<UserVO> listUsers(Integer page, Integer pageSize, String keyword, String status, Long departmentId) {
        log.info("获取用户列表: page={}, pageSize={}, keyword={}, status={}, departmentId={}",
                page, pageSize, keyword, status, departmentId);

        // 默认值
        int currentPage = page != null && page > 0 ? page : 1;
        int size = pageSize != null && pageSize > 0 ? pageSize : 20;

        // 构建查询条件
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();

        // 关键词搜索（用户名/全名/邮箱）
        if (keyword != null && !keyword.trim().isEmpty()) {
            wrapper.and(w -> w
                    .like(UserEntity::getUsername, keyword.trim())
                    .or().like(UserEntity::getFullName, keyword.trim())
                    .or().like(UserEntity::getEmail, keyword.trim()));
        }

        // 状态过滤
        if (status != null && !status.trim().isEmpty()) {
            wrapper.eq(UserEntity::getStatus, status.trim());
        }

        // 部门过滤
        if (departmentId != null) {
            wrapper.eq(UserEntity::getDepartmentId, departmentId);
        }

        // 排序：最新创建的在前
        wrapper.orderByDesc(UserEntity::getCreatedAt);

        // 执行分页查询
        Page<UserEntity> pageResult = new Page<>(currentPage, size);
        userMapper.selectPage(pageResult, wrapper);

        // 转换为VO
        List<UserVO> userVOList = pageResult.getRecords().stream()
                .map(this::toUserVO)
                .collect(Collectors.toList());

        // 构建分页结果
        long total = pageResult.getTotal();
        int totalPages = (int) Math.ceil((double) total / size);

        PagedResult<UserVO> result = PagedResult.<UserVO>builder()
                .items(userVOList)
                .pagination(PagedResult.Pagination.builder()
                        .page(currentPage)
                        .pageSize(size)
                        .total(total)
                        .totalPages(totalPages)
                        .build())
                .build();

        log.info("获取用户列表成功: 共 {} 条记录", total);
        return result;
    }

    /**
     * 修改密码
     *
     * @param userId  用户ID
     * @param request 修改密码请求
     */
    @Transactional
    public void changePassword(Long userId, ChangePasswordRequest request) {
        log.info("修改密码: userId={}", userId);

        // 1. 验证两次新密码是否一致
        if (!request.getNewPassword().equals(request.getConfirmPassword())) {
            throw new BusinessException("两次输入的新密码不一致");
        }

        // 2. 查询用户
        UserEntity user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 3. 验证旧密码
        if (!passwordEncoder.matches(request.getOldPassword(), user.getPassword())) {
            throw new BusinessException("旧密码不正确");
        }

        // 4. 更新密码
        user.setPasswordHash(passwordEncoder.encode(request.getNewPassword()));
        userMapper.updateById(user);

        log.info("密码修改成功: userId={}", userId);
    }

    /**
     * 重置密码（管理员操作）
     *
     * @param userId      用户ID
     * @param newPassword 新密码
     */
    @Transactional
    public void resetPassword(Long userId, String newPassword) {
        log.info("重置密码: userId={}", userId);

        UserEntity user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        user.setPasswordHash(passwordEncoder.encode(newPassword));
        userMapper.updateById(user);

        log.info("密码重置成功: userId={}", userId);
    }

    /**
     * 更新用户存储配额
     *
     * @param userId       用户ID
     * @param storageQuota 新配额（字节）
     */
    @Transactional
    public void updateStorageQuota(Long userId, Long storageQuota) {
        log.info("更新存储配额: userId={}, quota={}", userId, storageQuota);

        UserEntity user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        user.setStorageQuota(storageQuota);
        userMapper.updateById(user);

        log.info("存储配额更新成功: userId={}, quota={}", userId, storageQuota);
    }

    /**
     * 更新最后登录信息
     *
     * @param userId    用户ID
     * @param loginIp   登录IP
     */
    @Transactional
    public void updateLastLogin(Long userId, String loginIp) {
        UserEntity user = userMapper.selectById(userId);
        if (user == null) {
            return;
        }

        user.setLastLoginTime(LocalDateTime.now());
        user.setLastLoginIp(loginIp);
        userMapper.updateById(user);

        log.info("更新最后登录信息: userId={}, ip={}", userId, loginIp);
    }

    /**
     * 分配角色给用户
     *
     * @param userId    用户ID
     * @param roleCodes 角色代码列表
     */
    @Transactional
    public void assignRolesToUser(Long userId, List<String> roleCodes) {
        log.info("分配角色: userId={}, roles={}", userId, roleCodes);

        // 1. 删除现有角色关联
        userRoleMapper.delete(new LambdaQueryWrapper<UserRoleEntity>()
                .eq(UserRoleEntity::getUserId, userId));

        // 2. 添加新角色关联
        for (String roleCode : roleCodes) {
            RoleEntity role = roleMapper.selectByRoleCode(roleCode);
            if (role == null) {
                log.warn("角色代码不存在: {}", roleCode);
                continue;
            }

            UserRoleEntity userRole = new UserRoleEntity();
            userRole.setUserId(userId);
            userRole.setRoleId(role.getId());
            userRoleMapper.insert(userRole);
        }

        log.info("角色分配成功: userId={}, roleCount={}", userId, roleCodes.size());
    }

    /**
     * 获取用户角色列表
     *
     * @param userId 用户ID
     * @return 角色代码列表
     */
    public List<String> getUserRoles(Long userId) {
        List<RoleEntity> roles = roleMapper.selectRolesByUserId(userId);
        return roles.stream()
                .map(RoleEntity::getRoleCode)
                .collect(Collectors.toList());
    }

    /**
     * 转换为 UserVO
     */
    private UserVO toUserVO(UserEntity user) {
        UserVO vo = new UserVO();
        vo.setId(user.getId());
        vo.setUsername(user.getUsername());
        vo.setEmail(user.getEmail());
        vo.setFullName(user.getFullName());
        vo.setPhone(user.getPhone());
        vo.setAvatarUrl(user.getAvatarUrl());
        vo.setDepartmentId(user.getDepartmentId());
        vo.setStatus(user.getStatus());
        vo.setStorageQuota(user.getStorageQuota());
        vo.setStorageUsed(user.getStorageUsed());
        vo.setLastLoginTime(user.getLastLoginTime());
        vo.setLastLoginIp(user.getLastLoginIp());
        vo.setCreatedAt(user.getCreatedAt());
        vo.setUpdatedAt(user.getUpdatedAt());

        // 计算存储使用率
        if (user.getStorageQuota() != null && user.getStorageQuota() > 0) {
            double usagePercent = (user.getStorageUsed() * 100.0) / user.getStorageQuota();
            vo.setStorageUsagePercent(Math.round(usagePercent * 100.0) / 100.0);
        } else {
            vo.setStorageUsagePercent(0.0);
        }

        // 加载角色列表
        vo.setRoles(getUserRoles(user.getId()));

        // TODO: 加载部门名称（需要 DepartmentMapper）
        vo.setDepartmentName(null);

        return vo;
    }
}